from django.http import HttpResponse
from django.shortcuts import render_to_response
from django.contrib.auth.models import *
from django.db import IntegrityError
from django.core.exceptions import ObjectDoesNotExist
from django.contrib.sessions.backends.db import SessionStore
from django.contrib.sessions.models import Session
from django.utils import simplejson
import logging

from dl4.dailylang.models import *

logger = logging.getLogger(__name__)

def no_appkey(request, realm):
    my_dict = {'api': {
                   'response': {
                       'error': {
                           'code': -4,
                           'desc': {
                               'en': 'No application key.',
                               'pl': 'Brak klucza aplikacji.',
                           },
                       },
                   },
              }, }
    res = simplejson.dumps(my_dict)
    response = HttpResponse(res, mimetype="application/json")
#    response.status_code = 401
#    response['WWW-Authenticate'] = 'Basic realm="%s"' % realm
    return response

def appkey_unidentified(request, realm):
    my_dict = {'api': {
                   'response': {
                       'error': {
                           'code': -5,
                           'desc': {
                               'en': 'Application key not identified.',
                               'pl': 'Niezidentyfikowany klucz aplikacji.',
                           },
                       },
                   },
              }, }
    res = simplejson.dumps(my_dict)
    response = HttpResponse(res, mimetype="application/json")
#    response.status_code = 401
#    response['WWW-Authenticate'] = 'Basic realm="%s"' % realm
    return response

def appkey_in_cookie(request):
    return 'appkey' in request.session

def view_or_auth_app(view, request, test_func, realm = "", *args, **kwargs):
    """
    This is a helper function used by both 'logged_in_or_basicauth' and
    'has_perm_or_basicauth' that does the nitty of determining if they
    are already logged in or if they have provided proper http-authorization
    and returning the view if all goes well, otherwise responding with a 401.
    """
    # Log request data
    # 
    logger.debug('decorator; META are %s', request.META)
    logger.debug('decorator; COOKIES are %s', request.COOKIES)
    logger.debug('decorator; POST is %s', request.POST)

    # Log session data
    #
    session_key=request.session.session_key
    logger.debug('decorator; session key is %s', session_key)
    try:
        s = Session.objects.get(pk=session_key)
        logger.debug('decorator; session data are %s', s.get_decoded())
    except Session.DoesNotExist:
        logger.debug('decorator; session does not exist for key %s', session_key)

    # Request user
    # 
    logger.debug('decorator; request user is %s', request.user)

    # Is request authenticated?
    #
    logger.debug('decorator; is user authenticated? %s', request.user.is_authenticated())

    if test_func(request):
        # Return view
        #
        logger.debug('app_authenticaded found in session, returning view')
        return view(request, *args, **kwargs)

    # Search GET for appkey.
    #
    if not 'appkey' in request.GET:
        logger.debug('decorator; appkey not found in GET, returning 401')
        return no_appkey(request, "Application Key")
    logger.debug('decorator; appkey found in GET')

    # Read appkey from get
    #
    appkey = request.GET['appkey']
    logger.debug('decorator; appkey found in GET is %', appkey)

    # Verify app key against DB.
    #
    logger.debug('decorator; searching for appkey in database')
    try:
        appkey_record = AppKey.objects.get(appkey=appkey)
    except ObjectDoesNotExist:
        logger.debug('decorator; appkey not found in database, returning error')
        return appkey_unidentified(request, "Application Key")
    logger.debug('decorator; appkey found in database, but what is its status?')

    # Appkey found in database, but verify its status
    #
    status = appkey_record.status
    logger.debug('decorator; appkey status is %s', status)
    if status != "ACTIVE":
        logger.debug('decorator; appkey not active, returning 401')
        return appkey_unidentified(request, "Application Key")
    logger.debug('decorator; appkey active, storing it to session and passing control to view')
    
    # Set app_authenticated key in session.
    #
    logger.debug('decorator; setting app_authenticated into session and returning view')
    request.session['app_authenticated'] = True
    
    # Return view
    #
    return view(request, *args, **kwargs)

def appkey_required(realm = ""):
    def view_decorator(func):
        def wrapper(request, *args, **kwargs):
            return view_or_auth_app(func, request,
                                     lambda r: 'app_authenticated' in r.session,
                                     realm, *args, **kwargs)
        return wrapper
    return view_decorator
